package com.hp.snap.gr.action.impl;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hp.snap.gr.exception.ActionException;
import com.hp.snap.gr.model.jaxb.ActionType;
import com.hp.snap.gr.model.jaxb.GeneralActionType;
import com.hp.snap.gr.model.jaxb.ParameterType;
import com.hp.snap.gr.utils.Constants;
import com.hp.snap.gr.utils.GRMConfigManager;
import com.hp.snap.gr.utils.SSHTools;
import com.hp.snap.gr.utils.Utils;
import com.hp.snap.gr.model.HostInfo;
import com.hp.snap.gr.model.ServerInfo;

public class CheckNodeAvailableActionHandler extends AbstractActionHandler {

    private static Logger logger = LoggerFactory.getLogger(CheckNodeAvailableActionHandler.class);
    
    private static final String CPU_USAGE_PATTERN="^[1-9][0-9]*%";
    private static final String DISK_CAPACITY_PATTERN="^[1-9][0-9]*[G|g]";
    
    @Override
    public void execute(ActionType action, Map<String, Object> actionPlanInputs, Map<String, Object> actionPlanOutputs)
            throws ActionException {
        
        GeneralActionType actionType = (GeneralActionType) action;
        List<ParameterType> parameterTypes = actionType.getParameter();
        Map<String, String> parameterMap = Utils.contructParamMap(parameterTypes);
        
        String cpuUsage = parameterMap.get("CPU_USAGE");
        String diskHigh = parameterMap.get("DISK_HIGH_FREE");
        String disklower = parameterMap.get("DISK_LOWER_FREE");
        
        if(checkParamPattern(CPU_USAGE_PATTERN,cpuUsage)) {
            cpuUsage=cpuUsage.substring(0,cpuUsage.length()-1);
        }else{
            throw new ActionException("the parameter CPU_USAGE vaule ["+cpuUsage+"] setting error");
        }
        
        if(checkParamPattern(DISK_CAPACITY_PATTERN,diskHigh)) {
            diskHigh=diskHigh.substring(0,diskHigh.length()-1);
        }else{
            throw new ActionException("the parameter DISK_HIGH_FREE vaule ["+diskHigh+"] setting error");
        }
        
        if(checkParamPattern(DISK_CAPACITY_PATTERN,disklower)) {
            disklower=disklower.substring(0,disklower.length()-1);
        }else{
            throw new ActionException("the parameter DISK_LOWER_FREE vaule ["+disklower+"] setting error");
        }
        
        if (logger.isDebugEnabled()) {
            logger.debug("the cpu usage is {}", cpuUsage);
            logger.debug("the disk high setting is {}",diskHigh);
            logger.debug("the disk lower setting is {}", disklower);
        }
        
        
        @SuppressWarnings("unchecked")
        List<HostInfo> serverLst = (List<HostInfo>)actionPlanOutputs.get(Constants.SESSION_SERVER_RESPONSE_HOST); 
       
        
        int checkResult=0;
        int lostNodeCount=0;
        SSHTools ssh = null;
        for(HostInfo ssObj:serverLst){
            String remoteIp=ssObj.getHostIp();
            String sshUser = ssObj.getLogin();
            String sshKey = GRMConfigManager.decode("encrypt://"+ssObj.getSshKey());
            if(logger.isDebugEnabled()){
                logger.debug("remote ip:{}", remoteIp);
                logger.debug("sshUser is:{}", sshUser);
                logger.debug("encrypt ssh key is:{}",ssObj.getSshKey());
                logger.debug("SSH Key is:{}", sshKey);
            }
            File keyFile = Utils.generateKeyFile(sshKey);
            String keyFilePath ="";
            try {
                 keyFilePath = keyFile.getCanonicalPath();
                 
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            if(logger.isDebugEnabled()){
                logger.debug("The key file path is {}",keyFilePath);
            }
            
            
            String cmdresult;
            String shellScript = "/tmp/CheckNodeCondition.sh "+cpuUsage+" "+diskHigh+" "+disklower;
            String scriptFilename = Utils.getConfigurationValue("USER_GR_ARTIFACT")+"/CheckNodeCondition.sh";
            if (logger.isDebugEnabled()) {
                logger.debug("the check node shell script is: {}", shellScript);
            }
            ssh = new SSHTools(sshUser, keyFilePath);
            try {       
//                cmdresult = ssh.executeRemoteShell(true, shellScript, remoteIp);
                cmdresult=ssh.executeRemoteScriptFile(new File(scriptFilename), shellScript, remoteIp);
                int status = ssh.getExitStatusOfCommandResult(cmdresult);
                if(status==2 && checkResult<2)
                    checkResult=2;
                else if(status==1 && checkResult<1)
                    checkResult=1;
            } catch (Exception e) {
                lostNodeCount++;
                logger.error("execute the CheckNodeCondition.sh script failed by SSH connect to the {}",remoteIp);
                e.printStackTrace();
            }
//            keyFile.delete();
                 
        }
        if (ssh!=null) ssh.closeAll();
        //checking node available and lost node, 0:OK, 1:WARN, 2:ERROR
        if(lostNodeCount>1 || checkResult==2)
            checkResult=2;
        else if(lostNodeCount==1 || checkResult==1)
            checkResult=1;
        
       Constants.CONSOLE.info(checkResult+"");
    }
    
    
    private boolean checkParamPattern(String regEx, String param) {
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(param);
        boolean rs = matcher.matches();
        return rs;
    }
    
    

}
